class_name DelayCastSkillSys
extends System

var CATCH_READ = ["FrameTime", "Ext", "DelaySkillsC", "CastStateC", "BeCastStateC"]
var catch_read: Array

var dirty := []


func _init():
	system_name = "DelayCastSkillSys"
	listen_modify("on_use", "DelaySkillsC", [])
	listen_create("on_create", "Entities", ["CastStateC", "BeCastStateC"])


func _system_ready():
	catch_read = world.query_manager.fetch_components(CATCH_READ)


func _system_process(_delta):
	if not dirty.size():
		return
	var read = catch_read
	var frame = read[0].data
	var ext = read[1].data
	var delay_m = read[2]
	var action = read[3]
	var be_action = read[4]

	for fighter in dirty:
		var delay = delay_m.get(fighter)
		if delay_cast(frame, ext, action, be_action, delay, fighter):
			dirty.erase(fighter)


#listenModify(DelaySkillsC)
func on_use(e, _read: Array):
	dirty.append(e.id)


#listenCreate(Entities)
func on_create(e, read: Array):
	read[0].insert(e.id, Cast.CastStateC.new())
	read[1].insert(e.id, Cast.BeCastStateC.new())


static func delay_cast(frame: FrameTime, ext, action, be_action, delay: DelaySkillsC, fighter):
	var SkillAttrKey = C.SkillAttrKey
	var ActionState = C.ActionState

	if not ext.is_alive(fighter):
		return true
	var act = action.get(fighter) as Cast.CastStateC
	while true:
		var use_skill = delay.heap.get() as DelaySkillsC.UseSkill
		if not use_skill:
			return true
		if frame.count < use_skill.next_time:
			return false
		delay.heap.pop()
		#skill cost

		var skill = use_skill.skill
		var targets := []
		var be_acts := []

		for target in use_skill.targets:
			if ext.is_alive(target):
				targets.append(target)
				be_acts.append(be_action.get(target))

		if targets.size() == 0 && skill.get(SkillAttrKey.targetReSelect):
			pass
			#reselect here

		use_skill.targets = targets
		#
		act.skill = skill
		act.targets = targets
		act.action_target = {action = ActionState.cast, target = 0}

		for be_act in be_acts:
			be_act.skill = skill
			be_act.fighter = fighter
			be_act.action = ActionState.beCast

		# loop target check hit
		for i in range(targets.size() - 1, -1, -1):
			var target = targets[i]
			var be_act = be_acts[i]
			if ext.calc_skill_hit(skill, fighter, target):
				act.action_target = {action = ActionState.hit, target = target}
				be_act.action = ActionState.beHit
			else:
				act.action_target = {action = ActionState.miss, target = target}
				be_act.action = ActionState.dodge
			be_act.action = ActionState.none
		act.action_target = {action = ActionState.none, target = 0}
